package com.twb.auth.controller;

import java.time.LocalDateTime;

import javax.validation.constraints.NotBlank;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.twb.auth.common.TwbLoginUser;
import com.twb.auth.entity.twbAuth.vo.LoginUserVo;
import com.twb.auth.entity.twbOnline.TwbOnline;
import com.twb.auth.entity.twbProject.TwbProject;
import com.twb.auth.entity.twbUser.TwbUser;
import com.twb.auth.service.ITwbOnlineService;
import com.twb.auth.service.ITwbUserService;
import com.twb.core.base.Result;
import com.twb.core.base.controller.BaseController;
import com.twb.core.base.entity.BaseLoginUser;
import com.twb.core.security.TwbSecurityProperties;
import com.twb.core.security.TwbSecurityUtil;
import com.twb.core.security.annotation.Auth;
import com.twb.core.util.IpUtil;
import com.twb.core.util.Results;
import com.twb.core.util.cipher.MD5Util;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

@RestController
@RequestMapping("/sys/auth")
@Api(value = "TwbAuthController", tags = "用户登录授权接口")
public class TwbAuthController extends BaseController {

	private static Logger logger = LoggerFactory.getLogger(TwbAuthController.class);

	@Autowired
	ITwbUserService twbUserService;

	@Autowired
	ITwbOnlineService twbOnlineService;

	@Autowired
	TwbSecurityProperties securityProperties;

	@Autowired
	TwbSecurityUtil twbSecurityUtil;

	/**
	 * @param vo
	 * @return
	 * @Title login
	 * @Description 用户登录
	 * @author DSY
	 * @date 2018年11月6日 下午3:28:21
	 */
	@Auth(verifyToken = false, verifyURL = false)
	@PostMapping("/login")
	@ApiOperation(value = "用户登录")
	public Result<BaseLoginUser> login(LoginUserVo vo) {

		BaseLoginUser baseLoginUser = twbUserService.getLoginUserInfo(vo);
		String loginName = baseLoginUser.getLoginName();
		String ipAddr = IpUtil.getIpAddr(this.getRequest());
		baseLoginUser.setIp(ipAddr);

		// 创建Token
		String token = twbSecurityUtil.createToken(baseLoginUser, this.getRequest());
		baseLoginUser.setToken(token);
		logger.info(loginName + "已登录");

		TwbOnline online = new TwbOnline();
		online.setIp(baseLoginUser.getIp());
		online.setLoginName(loginName);
		// 登入
		online.setLoginType("1");
		// 管理后台
		online.setType("1");
		online.setCreateDate(LocalDateTime.now());
		online.setCreator(loginName);
		online.setCreatorId(baseLoginUser.getId());
		online.setIsdel(0);
		twbOnlineService.saveTwbOnline(online);
		return Results.successWithData(baseLoginUser);
	}

	/**
	 * @param openid
	 * @return
	 * @Title loginByOpenid
	 * @Description openid登录
	 * @author DSY
	 * @date 2022年7月29日 上午10:49:24
	 */
	@Auth(verifyToken = false, verifyURL = false)
	@PostMapping("/loginByOpenid")
	@ApiOperation(value = "用户登录")
	public Result<BaseLoginUser> loginByOpenid(@NotBlank(message = "openid不能为空") @RequestParam String openid) {

		TwbUser user = twbUserService.getUserByOpenId(openid);
		if (user == null) {
			return Results.failure("用户不存在");
		}

		BaseLoginUser baseLoginUser = twbUserService.getLoginUserInfoById(user.getId());
		String loginName = baseLoginUser.getLoginName();
		String ipAddr = IpUtil.getIpAddr(this.getRequest());
		baseLoginUser.setIp(ipAddr);

		// 创建Token
		String token = twbSecurityUtil.createToken(baseLoginUser, this.getRequest());
		baseLoginUser.setToken(token);
		logger.info(String.format("[%s]通过OpenId已登录", loginName));

		TwbOnline online = new TwbOnline();
		online.setIp(ipAddr);
		online.setLoginName(loginName);
		// 登入
		online.setLoginType("1");
		// 微信
		online.setType("2");
		online.setCreateDate(LocalDateTime.now());
		online.setCreator(loginName);
		online.setCreatorId(baseLoginUser.getId());
		online.setIsdel(0);
		twbOnlineService.saveTwbOnline(online);
		return Results.successWithData(baseLoginUser);
	}

	/**
	 * 企业微信用户ID登录
	 *
	 * @param cpUserId cp用户id
	 * @return {@link Result }<{@link BaseLoginUser }>
	 * @author DHL
	 * @date 2022-12-26 03:34:00
	 */
	@Auth(verifyToken = false, verifyURL = false)
	@PostMapping("/loginByCpUserId")
	@ApiOperation(value = "企业微信用户ID登录")
	public Result<BaseLoginUser> loginByCpUserId(@NotBlank(message = "企业微信用户不能为空") @RequestParam String cpUserId) {

		TwbUser user = twbUserService.getUserByCpUserId(cpUserId);
		if (user == null) {
			return Results.failure("用户不存在");
		}

		BaseLoginUser baseLoginUser = twbUserService.getLoginUserInfoById(user.getId());
		String loginName = baseLoginUser.getLoginName();
		String ipAddr = IpUtil.getIpAddr(this.getRequest());
		baseLoginUser.setIp(ipAddr);

		// 创建Token
		String token = twbSecurityUtil.createToken(baseLoginUser, this.getRequest());
		baseLoginUser.setToken(token);
		logger.info(String.format("[%s]通过OpenId已登录", loginName));

		TwbOnline online = new TwbOnline();
		online.setIp(ipAddr);
		online.setLoginName(loginName);
		// 登入
		online.setLoginType("1");
		// 企业微信
		online.setType("3");
		online.setCreateDate(LocalDateTime.now());
		online.setCreator(loginName);
		online.setCreatorId(baseLoginUser.getId());
		online.setIsdel(0);
		twbOnlineService.saveTwbOnline(online);
		return Results.successWithData(baseLoginUser);
	}

	/**
	 * @return
	 * @throws Exception
	 * @Title loginByToken
	 * @Description 通过token登录
	 * @author DSY
	 * @date 2018年11月6日 下午3:28:21
	 */
	@Auth(verifyToken = true, verifyURL = false)
	@PostMapping("/loginByToken")
	@ApiOperation(value = "用户通过Token验证登录")
	public Result<BaseLoginUser> loginByToken() throws Exception {

		try {
			boolean checkAndRefreshToken = twbSecurityUtil.checkAndRefreshToken(getRequest());

			if (checkAndRefreshToken) {
				BaseLoginUser baseLoginUser = twbSecurityUtil.getLoginUser(getRequest());
				TwbLoginUser loginUser = twbSecurityUtil.getTwbLoginUser(baseLoginUser.getToken());

				if(loginUser != null){
					return Results.successWithData(loginUser);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return Results.failure("Token验证失败!");
	}

	/**
	 * @param baseLoginUser
	 * @Title cacheLoginUserInfo
	 * @Description 缓存用户登录信息
	 * @author DSY
	 * @date 2022年7月29日 上午10:42:54
	 */
	private TwbLoginUser cacheLoginUserInfo(BaseLoginUser baseLoginUser) {
		String appId = twbSecurityUtil.getAppId(getRequest());
		Long timeoutSeconds = twbSecurityUtil.getTimeoutSeconds(getRequest());

		// 缓存用户登录详细信息
		TwbLoginUser user = twbUserService.cacheTwbLoginUserInfo(appId, baseLoginUser, timeoutSeconds);

		// 缓存用户数据权限信息
		twbUserService.cacheLoginUserDataScope(baseLoginUser, timeoutSeconds);
		// 缓存用户api权限
		twbUserService.cacheLoginUserApis(baseLoginUser, timeoutSeconds);

		return user;
	}

	/**
	 * @return com.twb.core.base.Result<com.twb.auth.common.TwbLoginUserDto>
	 * @Title getLoginUserCache
	 * @Description 查询登录用户信息 使用场景：系统切换重新获取资源等
	 * @author DHL
	 * @date 21:49 2022/7/18
	 */
	@Auth(verifyURL = false)
	@GetMapping("/getLoginUserCache")
	@ApiOperation(value = "查询登录用户信息")
	public Result<TwbLoginUser> getLoginUserCache() throws Exception {
		BaseLoginUser baseLoginUser = this.getLoginUser();
		TwbLoginUser loginUser = twbSecurityUtil.getTwbLoginUser(baseLoginUser.getToken());
		String appId = twbSecurityUtil.getAppId(getRequest());
		Boolean reCache = false;

		if (loginUser == null) {
			// 如果用户缓存为空，则重新加载缓存
			reCache = true;
		} else {
			// 如果当前项目和前端传入的项目APPID不一致，则重新加载缓存
			TwbProject app = loginUser.getApp();
			if (app == null && appId != null) {
				reCache = true;
			}
			if (app != null && !app.getAppId().equals(appId)) {
				reCache = true;
			}
		}
		// 是否重新加载缓存
		if (reCache) {
			loginUser = this.cacheLoginUserInfo(baseLoginUser);
		}
		return Results.successWithData(loginUser);
	}

	/**
	 * 刷新登录用户缓存 资源、权限、重新查询数据库更新缓存
	 * 
	 * @return
	 * @throws Exception
	 */
	@Auth(verifyURL = false)
	@GetMapping("/refreshLoginUserCache")
	@ApiOperation(value = "刷新登录用户缓存")
	public Result<TwbLoginUser> refreshLoginUserCache() throws Exception {
		BaseLoginUser loginUser = this.getLoginUser();

		// 登录用户
		TwbLoginUser user = this.cacheLoginUserInfo(loginUser);

		return Results.successWithData(user);
	}

	/**
	 * @return
	 * @Title logOut
	 * @Description 退出系统
	 * @author DSY
	 * @date 2018年11月27日 下午1:17:53
	 */
	@Auth(verifyToken = false, verifyURL = false)
	@PostMapping("/logOut")
	@ApiOperation(value = "用户退出")
	public Result<String> logOut() {
		BaseLoginUser loginUser = this.getLoginUser();

		if (loginUser == null) {
			return Results.success();
		}

		if (StringUtils.isNotEmpty(loginUser.getToken())) {
			twbSecurityUtil.removeLoginUser(loginUser.getToken());
		}
		TwbOnline online = new TwbOnline();
		online.setIp(loginUser.getIp());
		online.setLoginName(loginUser.getLoginName());
		online.setLoginType("0");// 登出
		online.setType("1");// 管理后台
		online.setCreateDate(LocalDateTime.now());
		online.setCreator(loginUser.getLoginName());
		online.setCreatorId(loginUser.getId());
		online.setIsdel(0);
		twbOnlineService.saveTwbOnline(online);
		return Results.success();
	}

	/**
	 * @return
	 * @Title getCurrentLoginUser
	 * @Class: TwbUserController.java
	 * @Description 获取当前登录用户信息
	 * @author DSY
	 * @date 2019年12月29日 下午2:11:38
	 */
	@Auth(verifyURL = false)
	@PostMapping("/getCurrentLoginUser")
	@ApiOperation(value = "获取当前登录用户信息")
	public Result<TwbLoginUser> getCurrentLoginUser() {
		return Results.successWithData(this.getLoginUser());
	}

	/**
	 * @param userId
	 * @param originalPassword
	 * @param newPassword
	 * @return
	 * @Title updateUserPwd
	 * @Description 修改用户密码
	 * @AuthorOriginally DSY
	 * @date 2022年7月26日 下午3:25:03
	 */
	@Auth(verifyURL = false)
	@PostMapping("/updateUserPwd")
	@ApiOperation(value = "用户密码修改")
	public Result<String> updateUserPwd(
			@NotBlank @RequestParam @ApiParam(value = "用户ID", name = "userId", required = true) String userId,
			@NotBlank @RequestParam @ApiParam(value = "原密码", name = "originalPassword", required = true) String originalPassword,
			@NotBlank @RequestParam @ApiParam(value = "新密码", name = "newPassword", required = true) String newPassword) {

		TwbUser twbUser = twbUserService.getById(userId);
		if (twbUser == null) {
			return Results.failure("未查询到用户信息!");
		}
		if (!MD5Util.verify(originalPassword, twbUser.getPwd())) {
			return Results.failure("原密码输入错误!");
		}
		boolean result = twbUserService.updateUserPwd(userId, newPassword);
		if (result) {
			return Results.success("密码修改成功");
		} else {
			return Results.failure("密码修改失败");
		}
	}
}
